package com.apes.fn.server.servicePlan.service;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.pi.fnCommunal.FnCommunalService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.area.model.BusinessCircle;
import com.apes.scm.masterdata.car.model.CarServiceLevel;
import com.apes.scm.masterdata.car.service.CarServiceLevelService;
import com.apes.scm.masterdata.finance.model.CooperateType;
import com.apes.scm.masterdata.finance.repository.CooperateTypeRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.model.Store;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.merchant.model.Merchant;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.AccessProviderRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import lombok.Data;
import lombok.experimental.Accessors;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * @program: apes-server
 * @description 条件策略建造
 * @author: czs
 * @create: 2022-04-22 09:54
 **/
public class ConditionBuilder extends DomainService {

    private final String conditionStrategyId;
    private final String conditionId;

    //公司部门相关信息
    private final String SUPPLIER_ID;
    private final String COMPANY_ID;
    private final String SAL_COMPANY_ID;
    private final String PUR_COMPANY_ID;
    private final String ACCESS_PROVIDER_ID;
    private final String DEPT_ID;
    private final String BUSINESS_CIRCLE_ID;
    private final String COOPERATION_TYPE;
    private final String OPERATION;
    private final String OPERATOR_ID;

    //车辆信息
    private final String PHONE_NUMBER;
    private final String VIP_IDENTITY_ID;
    private final String VIP_LEVEL_ID;
    private final String CAR_SERVICE_LEVEL_ID;
    private final String CAR_LICENSE;
    private final String CUSTOMER_ID;
    private final String CJHM;

    //商品信息
    private final String PRODUCT_ID;
    private final String PRODUCT_NAME;
    private final String CLASSIFY_ID;
    private final String BRAND_ID;
    private final long PRODUCT_UOM_ID;
    private final String QUALITY;
    private final Double USABLE_QTY;
    private final String SUB_QUALITY_ID;
    private final boolean CONTAIN_SPACE;
//    private final String WORK_TYPE;

    //价格相关
    private final Double P001;
    private final Double XSDJ;
    private final Double XSXJ;
    private final Map SPECIAL_INFO;

    //额外信息
    private final String uniqueIdentify;
    private final String SYS_NO_CHECK;
    private final Date SYS_RQ = new Date();

    //结果
    private Map paramMap;
    private Object result;
    private JSONObject resultJson;
    private Map resultMap;

    private ConditionBuilder(Builder builder) {
        //基础信息
        this.conditionStrategyId = builder.conditionStrategyId;
        this.conditionId = builder.conditionId;

        //公司部门相关信息
        this.SUPPLIER_ID = builder.supplierId;
        this.PUR_COMPANY_ID = builder.purCompanyId;
        this.SAL_COMPANY_ID = builder.salCompanyId;
        this.COMPANY_ID = builder.companyId;
        this.ACCESS_PROVIDER_ID = builder.accessProviderId;
        this.DEPT_ID = builder.deptId;
        this.BUSINESS_CIRCLE_ID = builder.businessCircleId;
        this.COOPERATION_TYPE = builder.cooperationType;
        this.OPERATION = builder.operation;
        this.OPERATOR_ID = builder.merchantId;

        //车辆信息
        this.PHONE_NUMBER = builder.phoneNumber;
        this.VIP_IDENTITY_ID = builder.vipIdentityId;
        this.VIP_LEVEL_ID = builder.vipLevelId;
        this.CAR_SERVICE_LEVEL_ID = builder.carServiceLevelId;
        this.CAR_LICENSE = builder.carLicense;
        this.CUSTOMER_ID = builder.customerId;
        this.CJHM = builder.CJHM;

        //商品信息
        this.PRODUCT_ID = builder.productId;
        this.PRODUCT_NAME = builder.productName;
        this.CLASSIFY_ID = builder.classifyId;
        this.BRAND_ID = builder.brandId;
        this.PRODUCT_UOM_ID = builder.productUomId;
        this.QUALITY = builder.quality;
        this.USABLE_QTY = builder.usableQty;
        this.SUB_QUALITY_ID = builder.subQuality;
        this.CONTAIN_SPACE = builder.containSpace;
//        this.WORK_TYPE = builder.workType;

        //价格相关
        this.P001 = builder.P001;
        this.XSDJ = builder.XSDJ;
        this.XSXJ = builder.XSXJ;
        this.SPECIAL_INFO = builder.specialInfo;
        //额外信息
        this.SYS_NO_CHECK = builder.sysNoCheck;
        this.uniqueIdentify = builder.uniqueIdentify;
        //格式化成价格策略的参数
        this.paramMap = toMap();
    }

    @Data
    @Accessors(chain = true)
    public static class Builder {
        private final String conditionStrategyId;
        private final String conditionId;
        //公司部门相关信息
        private String supplierId;
        private String purCompanyId;
        private String salCompanyId;
        private String companyId;
        private String accessProviderId;
        private String deptId;
        private String businessCircleId;
        private String cooperationType;
        private String operation;
        private String merchantId;

        //车辆信息
        private String phoneNumber;
        private String vipIdentityId;
        private String vipLevelId;
        private String carServiceLevelId;
        private String carLicense;
        private String customerId;
        private String CJHM;

        //商品信息
        private String brandId;
        private String productId;
        private String productName;
        private String classifyId;
        private long productUomId;
        private String quality;
        private String subQuality;
        private boolean containSpace;
//        private String workType;
        private Double usableQty = 0.0D;

        //价格相关
        private Double P001;
        private Double XSDJ;
        private Double XSXJ;

        //额外信息
        private String sysNoCheck;
        private String uniqueIdentify;
        //特殊信息 会把里面的参数单独取出
        private Map specialInfo;


        public Builder(String conditionStrategyId) {
            this.conditionStrategyId = conditionStrategyId;
            this.conditionId = conditionStrategyId;
        }
        //公司部门相关信息

        /**
         * 设置部门信息
         * @param dept
         * @return
         */
        public Builder setDept(Dept dept) {
            if (dept == null) throw new RuntimeException("获取门店失败");
            Store store = SpringManager.getBean(StoreRepository.class).findByDept(dept);
            this.containSpace = store.isContainSpace();
            this.companyId = dept.getCompany().getId();
            if (this.salCompanyId == null) this.salCompanyId = dept.getCompany().getId();
            this.deptId = dept.getId();

            try {
                this.accessProviderId = SpringManager.getBean(AccessProviderRepository.class).findByCompany(dept.getCompany().getId()).getId();
            } catch (Exception e) {
                e.printStackTrace();
            }
//            if (this.accessProviderId == null&&dept.getCompany().getAccessProvider()!=null) this.accessProviderId = dept.getCompany().getAccessProvider().getId();
            if (this.businessCircleId == null&&store.getBusinessCircle()!=null) this.businessCircleId = store.getBusinessCircle().getId();
            try {
                if (this.operation == null)
                    this.operation = dept.getCompany().getParty().getCorporate().getOperation().getId();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this;
        }


        public Builder setBusinessCircle(BusinessCircle businessCircle) {
            if (businessCircle==null)return this;
            this.businessCircleId = businessCircle.getId();
            return this;
        }


        public Builder setDept(String deptId) {
            this.setDept(SpringManager.getBean(DeptRepository.class).findOne(deptId));
            return this;
        }

        public Builder setPlatform(PartyRole platform) {
            this.purCompanyId = platform.getId();
            return this;
        }

        public Builder setPlatform(String platform) {
            this.purCompanyId = platform;
            return this;
        }

        public Builder setSupplierId(String supplierId) {
            if (supplierId==null) return setSysNoCheck("SUPPLIER_ID");
            this.supplierId = supplierId;
            return this;
        }
        public Builder setSupplierId(PartyRole supplier) {
            if (supplier==null){
                return setSysNoCheck("SUPPLIER_ID");
            }
            return setSupplierId(supplier.getId());
        }


        public Builder setCooperationType(CooperateType cooperationType) {
            if (cooperationType == null) return this;
            this.cooperationType = cooperationType.getId();
            return this;
        }

        //车辆信息
        public Builder fnCustomer(Map fnCustomerMap) {
            fnCustomer(new JSONObject(fnCustomerMap));
            return this;
        }

        public Builder fnCustomer(JSONObject fnCustomer) {
            if (fnCustomer.isEmpty()) throw new RuntimeException("车辆信息为空");
            fnCustomer.putAll(fnCustomer.getJSONObject("customer"));
            this.vipLevelId = fnCustomer.getString("level");
            if (this.accessProviderId == null) this.accessProviderId = fnCustomer.getString("vendorCode");
            this.carServiceLevelId = ((CarServiceLevel) (SpringManager.getBean(CarServiceLevelService.class).findByCarConfigurationId(fnCustomer.getString("jekunModelCode")))).getId();
            this.carLicense = fnCustomer.getString("carLicense");
            this.phoneNumber = fnCustomer.getString("mobile");
            this.CJHM = fnCustomer.getString("vin");
            this.vipIdentityId = fnCustomer.getJSONObject("userRole") == null ? null : fnCustomer.getJSONObject("userRole").getString("id");
            if (this.customerId == null)
                this.customerId = fnCustomer.getJSONObject("unitClient") == null ? null : fnCustomer.getJSONObject("unitClient").getString("clientCode");
            return this;
        }

        //商品信息
        public Builder product(Product product) {
            this.productId = product.getId();
            this.productName = product.getName();
            if (uniqueIdentify == null) this.uniqueIdentify = product.getId();
            this.brandId = product.getBrand().getId();
            this.classifyId = product.getClassify().getId();
            this.productUomId = product.getUom().getId();
            if(product.getBrand().getQuality()!=null)this.quality = product.getBrand().getQuality().getId();
            if(product.getBrand().getSubQuality()!=null)this.subQuality = product.getBrand().getSubQuality().getId();
            return this;
        }

        public Builder productId(String productId) {
            Product product = SpringManager.getBean(ProductRepository.class).findOne(productId);
            return product(product);
        }

        //价格相关
        public Builder setXJ(Double p001, Double XSDJ, Double XSXJ) {
            this.P001 = p001;
            this.XSDJ = XSDJ;
            this.XSXJ = XSXJ;
            return this;
        }


        public Builder setMerchant(Merchant merchant) {
            if (merchant!=null)this.merchantId = merchant.getId();
            return this;
        }

        public ConditionBuilder build() {
            return new ConditionBuilder(this);
        }
    }

    /**
     * 执行价格策略
     * @return
     */
    public ConditionBuilder execConditionStrategy() {
        Object obj = null;
        try {
            obj = this.invoke("condition.execConditionStrategy", this.paramMap);
        } catch (Exception e) {
            throw new RuntimeException("执行条件策略报错,错误信息为:"+e.getMessage());
        }
        this.result = obj;
//        this.resultMap = MapUtil.mapped(obj);
//        this.resultJson = new JSONObject(resultMap);
        return this;
    }

    /**
     * 格式化金额
     * @param scale
     * @return
     */
    public ConditionBuilder formatAmount(int scale){
        if (result==null)return this;
        result = priceRoundUp(result,scale);
        return this;
    }

    /**
     * 格式化金额
     * @return
     */
    public ConditionBuilder formatAmount(){
        formatAmount(2);
        return this;
    }

    /**
     * 获取map结果
     * @return
     */
    public Map getResultMap() {
        if (this.result == null) throw new RuntimeException("请确认是否执行过价格策略");
        if (this.resultMap == null) this.resultMap = MapUtil.mapped(this.result);
        return resultMap;
    }

    public ConditionBuilder execCondition() {
        Object obj = null;
        try {
            obj = this.invoke("condition.getCondition", this.paramMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.result = obj;
//        this.resultMap = MapUtil.mapped(obj);
//        this.resultJson = new JSONObject(resultMap);
        return this;
    }



    private Object priceRoundUp(Object jsonObjParam, int scale) {

        Set<Map.Entry<String, Object>> entries = getEntries(jsonObjParam);

        jsonObjParam = getRoundUpDouble(scale, entries);

        return jsonObjParam;
    }


    private Set<Map.Entry<String, Object>> getEntries(Object jsonObjParam) {
        Set<Map.Entry<String, Object>> entries = null;
        if (jsonObjParam instanceof JSONObject){
            JSONObject jsonObject = (JSONObject) jsonObjParam;
            entries = jsonObject.entrySet();
        }else if (jsonObjParam instanceof com.apestech.framework.json.JSONObject){
            com.apestech.framework.json.JSONObject jsonObject = (com.apestech.framework.json.JSONObject) jsonObjParam;
            entries = jsonObject.entrySet();
        }else{
            throw new RuntimeException("获取未知类型迭代器");
        }
        return entries;
    }

    /**
     * 格式化金额
     * -格式化为两位小数
     * -统一返回Double格式
     * @param scale
     * @param entries
     * @return
     */
    private JSONObject getRoundUpDouble(int scale, Set<Map.Entry<String, Object>> entries) {
        JSONObject result = new JSONObject();
        for (Map.Entry<String, Object> next : entries) {
            Object value = next.getValue();
            if (value instanceof Double&&!((Double) value).isNaN()) {
                result.put(next.getKey(), Arith.round((Double) value, scale, BigDecimal.ROUND_UP));
            }else if (value instanceof BigDecimal){
                BigDecimal bigDecimal = (BigDecimal) value;
                result.put(next.getKey(), Arith.round(bigDecimal.doubleValue(), scale, BigDecimal.ROUND_UP));
            }else {
                result.put(next.getKey(), value);
            }

        }
        return result;
    }
    private Map toMap() {
        Map result = new HashMap();
        Field[] declaredFields = this.getClass().getDeclaredFields();
        List<Field> fieldList = Arrays.asList(declaredFields);
        fieldList.forEach(field -> {
            field.setAccessible(true);
            try {
                String name = field.getName();
                Object o = field.get(this);
                if (name.equals("SPECIAL_INFO")){
                    if (o instanceof Map){
                        result.putAll((Map) o);
                    }
                }else {
                    if (o != null) result.put(name, o);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return result;
    }

    public JSONObject getResultJson() {
        if (this.resultJson == null) this.resultJson = new JSONObject(getResultMap());
        return this.resultJson;
    }

    public JSONObject toJsonObject() {
        if (this.paramMap == null) return new JSONObject();
        return new JSONObject(this.paramMap);
    }

    public Map getParamMap() {
        return paramMap;
    }
}
